package org.edu.modules.stu.base.controller;


import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.shiro.SecurityUtils;
import org.apache.xmlbeans.impl.common.SystemCache;
import org.edu.common.base.ConditionDto;
import org.edu.common.dto.BaseCountDto;
import org.edu.common.dto.ExcelPo;
import org.edu.common.system.api.ISysBaseAPI;
import org.edu.common.system.vo.DictModel;
import org.edu.common.system.vo.LoginUser;
import org.edu.common.util.*;
import org.edu.common.utils.PoiUtils;
import org.edu.modules.stu.base.dto.*;
import org.edu.common.dto.AllDto;
import org.edu.modules.stu.base.entity.VeBaseStudent;
import org.edu.modules.stu.base.entity.VeBaseStudentInfo;
import org.edu.modules.stu.base.entity.VeStuFamily;
import org.edu.modules.stu.base.service.VeBaseStudentInfoService;
import org.edu.modules.stu.base.service.VeBaseStudentService;
import org.edu.common.api.vo.Result;
import org.edu.common.base.PageDto;
import org.edu.common.dto.StatusDto;
import org.edu.common.aspect.annotation.AutoLog;
import org.edu.common.system.query.QueryGenerator;
import org.edu.modules.stu.base.service.VeStuFamilyService;
import org.edu.modules.stu.base.utils.DateTimeUtil;
import org.edu.modules.stu.base.utils.ExcelUtils;
import org.edu.modules.stu.base.utils.OptimizedExcelValidator;
import org.edu.modules.stu.common.entity.VeBaseAppUser;
import org.edu.modules.stu.common.entity.VeBaseBanji;
import org.edu.modules.stu.common.entity.VeBaseTeacher;
import org.edu.modules.stu.common.service.VeBaseAppUserService;
import org.edu.modules.stu.common.service.VeBaseBanjiService;
import org.edu.modules.stu.common.service.VeBaseTeacherService;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;


import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.jeecgframework.poi.util.ExcelUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ReadListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Api(tags = {"学生信息表"})
@RestController
@RequestMapping("/stu/veBaseStudent")
@Slf4j
public class VeBaseStudentController {

    @Autowired
    private VeBaseStudentService veBaseStudentService;
    @Autowired
    private VeBaseStudentInfoService veBaseStudentInfoService;

    @Autowired
    private VeBaseStudentInfoService infoService;

    @Autowired
    private VeStuFamilyService veStuFamilyService;

    @Autowired
    private VeBaseAppUserService veBaseAppUserService;

    @Autowired
    private VeBaseTeacherService veBaseTeacherService;

    @Autowired
    private VeBaseBanjiService veBaseBanjiService;
    @Qualifier("org.edu.common.system.api.ISysBaseAPI")
    @Autowired
    private ISysBaseAPI iSysBaseAPI;

    private Map<String, List<DictModel>> dictModelListMap;

    @ApiOperation("分页查询学生信息表")
    @PostMapping("/page")
    public Result<?> page(@RequestBody PageDto<VeBaseStudent> page) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        if (oConvertUtils.isEmpty(sysUser)) {
            return Result.error("请登录系统！");
        }
        //根据用户id查用户信息
        VeBaseAppUser appUser = veBaseAppUserService.getVeBaseAppUserById(sysUser.getId());
        IPage<VeBaseStudentDto> pageDto = null;
        QueryWrapper<VeBaseStudent> queryWrapper = page.buildQueryWrapper(VeBaseStudent.class);
        if (appUser.getUserType().contains("1")) {
            //如果用户类型是1，为教师账号
            //如果有传班级id，直接根据班级id查
            ListIterator<ConditionDto> iterator = page.getConditions().listIterator();
            while (iterator.hasNext()) {
                int currentIndex = iterator.nextIndex();
                // 获取当前行（元素）
                ConditionDto currentCondition = iterator.next();
                // 处理当前元素
                if (page.getConditions().get(currentIndex).getColumn().equals("bj_id") == true) {
                    pageDto = veBaseStudentService.pageDto(page, queryWrapper);
                    return Result.OK(pageDto);
                }
            }
            //根据工号查教师信息
            //VeBaseTeacher baseTeacher = veBaseTeacherService.getByUserId(appUser.getUserId());
            //查班级
            List<VeBaseBanji> baseBanjis = veBaseBanjiService.listByTeacherId(appUser.getUserId());
            if (baseBanjis != null && baseBanjis.size() > 0) {
                //该教师是班主任，查班级下学生
                StringBuilder sb = new StringBuilder();
                for (VeBaseBanji baseBanji : baseBanjis) {
                    //遍历班级，获取班级id
                    sb.append(baseBanji.getId()).append(",");  // 添加分隔符
                }
                // 去除末尾多余的分隔符
                String baseBanjiIds = sb.length() > 0 ? sb.deleteCharAt(sb.length() - 1).toString() : "";
                String[] ids = baseBanjiIds.split(",");
                pageDto = veBaseStudentService.pageDtoByBanjinIds(page, queryWrapper, ids);
            } else {
                //不是班主任，看全部
                pageDto = veBaseStudentService.pageDto(page, queryWrapper);
            }
        } else {
            //管理员
            pageDto = veBaseStudentService.pageDto(page, queryWrapper);
        }
        return Result.OK(pageDto);
    }

    /**
     * 查询所有
     */
    @ApiOperation("查询所有")
    @PostMapping("/all")
    public Result<?> all(@RequestBody AllDto<VeBaseStudent> page) {
        QueryWrapper<VeBaseStudent> queryWrapper = page.buildQueryWrapper(VeBaseStudent.class);
        List<VeBaseStudent> list = veBaseStudentService.listByWrapper(queryWrapper);
        return Result.OK(list);
    }

    @AutoLog(value = "统计困难生")
    @ApiOperation(value = "统计困难生", notes = "统计困难生")
    @GetMapping(value = "/countKns")
    public Result<List<BaseCountDto>> countKns(@RequestParam(name = "year", required = false) String year) {
        return Result.OK(veBaseStudentService.countDto(year));
    }

    @AutoLog(value = "历届毕业生统计")
    @ApiOperation(value = "历届毕业生统计", notes = "历届毕业生统计")
    @GetMapping(value = "/graduateStatistics")
    public Result<List<BaseCountDto>> graduateStatistics(@RequestParam(name = "falId", required = false) Integer falId,
                                                         @RequestParam(name = "specId", required = false) Integer specId) {
        return Result.OK(veBaseStudentService.graduateStatistics(falId, specId));
    }

    @AutoLog(value = "统计在校生")
    @ApiOperation(value = "统计在校生", notes = "统计在校生")
    @GetMapping(value = "/countStudentAtSchool")
    public Result<List<BaseCountDto>> countStudentAtSchool(@RequestParam(name = "gradeId", required = false) String gradeId,
                                                           @RequestParam(name = "falId", required = false) String falId,
                                                           @RequestParam(name = "specId", required = false) String specId,
                                                           @RequestParam(name = "bjId", required = false) String bjId) {
        return Result.OK(veBaseStudentService.countStudentAtSchool(gradeId, falId, specId, bjId));
    }


    @ApiOperation("导出数据）")
//    @PostMapping("/export")
    public Result<?> export(@RequestBody PageDto<VeBaseStudent> page, HttpServletResponse resp) {
        QueryWrapper<VeBaseStudent> queryWrapper = page.buildQueryWrapper(VeBaseStudent.class);
        List<ExcelPo> list = new ArrayList<>();
        list.add(new ExcelPo("身份证号", "sfzh"));
        list.add(new ExcelPo("学号", "xh"));
        list.add(new ExcelPo("姓名", "xm"));
        list.add(new ExcelPo("性别", "xbm", "sexStr"));
        list.add(new ExcelPo("民族", "mzm", "mzm"));
        list.add(new ExcelPo("所属年级", "gradeText"));
        list.add(new ExcelPo("入学年月", "rxny"));
//        list.add(new ExcelPo("招生类型", "rxDate"));
        list.add(new ExcelPo("修读专业", "specText"));
        list.add(new ExcelPo("学制", "xz", "xz"));
        list.add(new ExcelPo("班级", "bjText"));
        list.add(new ExcelPo("所在省份", "province"));
        list.add(new ExcelPo("所在市", "city"));
        list.add(new ExcelPo("所在区", "county"));
        list.add(new ExcelPo("详情地址", "hkxxdz"));
        list.add(new ExcelPo("报名号", "bmh"));
        list.add(new ExcelPo("健康状况", "jkzkm", "jkzkm"));
        list.add(new ExcelPo("政治面貌", "zzmmm", "zzmmm"));
        list.add(new ExcelPo("户口类别", "hklbm", "hklbm"));
        list.add(new ExcelPo("是否低保", "sfdb", "shifou"));
        list.add(new ExcelPo("就读方式", "jdfs", "jdfs"));
        list.add(new ExcelPo("状态", "xsdqztm", "stuStatye"));



/*
        list.add(new ExcelPo("所属院系ID","falId"));

        list.add(new ExcelPo("生源地省id","sProvince"));
        list.add(new ExcelPo("生源地市id","sCity"));
        list.add(new ExcelPo("生源地区id","sCounty"));
        list.add(new ExcelPo("是否是困难生 0=否  1=是","sfkns"));
        list.add(new ExcelPo("准考证号","zkzh"));
        list.add(new ExcelPo("考生号","ksh"));
        list.add(new ExcelPo("更新状态（0：未更新; 1：已更新）","updateStatus"));
        list.add(new ExcelPo("学生ID","stuId"));
        list.add(new ExcelPo("曾用名","cym"));
        list.add(new ExcelPo("出生日期","csDate"));
        list.add(new ExcelPo("籍贯","jg"));
        list.add(new ExcelPo("健康状况码","jkzkm"));
        list.add(new ExcelPo("政治面貌码","zzmmm"));

        list.add(new ExcelPo("是否是流动","sfsldrk"));

        list.add(new ExcelPo("家庭联系电话","homePhone"));
        list.add(new ExcelPo("特长","tc"));
        list.add(new ExcelPo("学生联系电话","phone"));
        list.add(new ExcelPo("电子信箱","email"));
        list.add(new ExcelPo("照片","photo"));
        list.add(new ExcelPo("即时通讯号","qq"));
        list.add(new ExcelPo("是否低保0否1是","sfdb"));
        list.add(new ExcelPo("毕业学校","byxx"));
        list.add(new ExcelPo("报名方式","bmfsm"));
        list.add(new ExcelPo("入学成绩","rxcj"));
        list.add(new ExcelPo("家庭地址是否公开 1公开2不公开","jtdzStatus"));
        list.add(new ExcelPo("联系电话是否公开 1公开2不公开","xslxdhStatus"));*/
        PoiUtils.downloadFile(resp, veBaseStudentService.pageDto(page, queryWrapper).getRecords(), list);
        return Result.OK();
    }

    @ApiOperation("导出数据")
//    @GetMapping("/export2")
    public Result<?> export2(VeBaseStudent veBaseStudent, HttpServletRequest req, HttpServletResponse resp) {
        QueryWrapper<VeBaseStudent> queryWrapper = QueryGenerator.initQueryWrapper(veBaseStudent, req.getParameterMap());
        List<ExcelPo> list = new ArrayList<>();
        list.add(new ExcelPo("身份证号", "sfzh"));
        list.add(new ExcelPo("学号", "xh"));
        list.add(new ExcelPo("姓名", "xm"));
        list.add(new ExcelPo("性别", "xbm", "sexStr"));
        list.add(new ExcelPo("民族", "mzm", "mzm"));
        list.add(new ExcelPo("所属年级", "gradeText"));
        list.add(new ExcelPo("入学年月", "rxny"));
//        list.add(new ExcelPo("招生类型", "rxDate"));
        list.add(new ExcelPo("修读专业", "specText"));
        list.add(new ExcelPo("学制", "xz", "xz"));
        list.add(new ExcelPo("班级", "bjText"));
        list.add(new ExcelPo("所在省份", "province"));
        list.add(new ExcelPo("所在市", "city"));
        list.add(new ExcelPo("所在区", "county"));
        list.add(new ExcelPo("详情地址", "hkxxdz"));
        list.add(new ExcelPo("报名号", "bmh"));
        list.add(new ExcelPo("健康状况", "jkzkm", "jkzkm"));
        list.add(new ExcelPo("政治面貌", "zzmmm", "zzmmm"));
        list.add(new ExcelPo("户口类别", "hklbm", "hklbm"));
        list.add(new ExcelPo("是否低保", "sfdb", "shifou"));
        list.add(new ExcelPo("就读方式", "jdfs", "jdfs"));
        list.add(new ExcelPo("状态", "xsdqztm", "stuStatye"));



/*
        list.add(new ExcelPo("所属院系ID","falId"));

        list.add(new ExcelPo("生源地省id","sProvince"));
        list.add(new ExcelPo("生源地市id","sCity"));
        list.add(new ExcelPo("生源地区id","sCounty"));
        list.add(new ExcelPo("是否是困难生 0=否  1=是","sfkns"));
        list.add(new ExcelPo("准考证号","zkzh"));
        list.add(new ExcelPo("考生号","ksh"));
        list.add(new ExcelPo("更新状态（0：未更新; 1：已更新）","updateStatus"));
        list.add(new ExcelPo("学生ID","stuId"));
        list.add(new ExcelPo("曾用名","cym"));
        list.add(new ExcelPo("出生日期","csDate"));
        list.add(new ExcelPo("籍贯","jg"));
        list.add(new ExcelPo("健康状况码","jkzkm"));
        list.add(new ExcelPo("政治面貌码","zzmmm"));

        list.add(new ExcelPo("是否是流动","sfsldrk"));

        list.add(new ExcelPo("家庭联系电话","homePhone"));
        list.add(new ExcelPo("特长","tc"));
        list.add(new ExcelPo("学生联系电话","phone"));
        list.add(new ExcelPo("电子信箱","email"));
        list.add(new ExcelPo("照片","photo"));
        list.add(new ExcelPo("即时通讯号","qq"));
        list.add(new ExcelPo("是否低保0否1是","sfdb"));
        list.add(new ExcelPo("毕业学校","byxx"));
        list.add(new ExcelPo("报名方式","bmfsm"));
        list.add(new ExcelPo("入学成绩","rxcj"));
        list.add(new ExcelPo("家庭地址是否公开 1公开2不公开","jtdzStatus"));
        list.add(new ExcelPo("联系电话是否公开 1公开2不公开","xslxdhStatus"));*/
        List<VeBaseStudent> list2 = veBaseStudentService.listByWrapper(queryWrapper);
        PoiUtils.downloadFile(resp, list2, list);
        return Result.OK();
    }

    @AutoLog(value = "学生信息表-分页列表查询")
    @ApiOperation(value = "学生信息表-分页列表查询", notes = "学生信息表-分页列表查询")
    @PostMapping(value = "/list")
    public Result<?> queryPageList(VeBaseStudent entity,
                                   @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                   HttpServletRequest req) {
        QueryWrapper<VeBaseStudent> queryWrapper = QueryGenerator.initQueryWrapper(entity, req.getParameterMap());
        PageDto<VeBaseStudent> page = new PageDto<VeBaseStudent>(pageNo, pageSize);
        IPage<VeBaseStudent> pageList = veBaseStudentService.page(page, queryWrapper);
        return Result.OK(pageList);
    }


    @AutoLog(value = "通过id查询")
    @ApiOperation(value = "通过id查询", notes = "通过id查询")
    @GetMapping(value = "/queryById")
    public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
        VeBaseStudentDto dto = veBaseStudentService.findDtoById(id);
        VeBaseStudentInfoDto infoDto = infoService.findDtoByStuId(id);
        VeStudentVo veStudentVo = new VeStudentVo();
        veStudentVo.setStu(dto);
        veStudentVo.setStuInfo(infoDto);
        if (dto == null) {
            return Result.error("未找到对应数据");
        }
        return Result.OK(veStudentVo);
    }

    @AutoLog(value = "获取当前学生学籍")
    @ApiOperation(value = "获取当前学生学籍", notes = "获取当前学生学籍")
    @GetMapping(value = "/queryByLogin")
    public Result<?> queryByLogin(HttpServletRequest request) {
        //直接获取当前用户不适用前端token
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        if (oConvertUtils.isEmpty(loginUser)) {
            return Result.error("请登录系统！");
        }

        VeBaseStudentDto dto = veBaseStudentService.findDtoByXh(loginUser.getUsername());
        if (dto == null) {
            return Result.error("未找到对应学生信息");
        }
        VeBaseStudentInfoDto infoDto = infoService.findDtoByStuId(dto.getId().toString());
        if (dto == null) {
            return Result.error("未找到对应学生详细信息");
        }
        VeStudentVo veStudentVo = new VeStudentVo();
        veStudentVo.setStu(dto);
        veStudentVo.setStuInfo(infoDto);

        return Result.OK(veStudentVo);
    }


    @AutoLog(value = "添加")
    @ApiOperation(value = "添加", notes = "添加")
    @PostMapping(value = "/add")
    public Result<?> add(@RequestBody VeStudentVo dto) {
        veBaseStudentService.insertOrUpdate(dto, true);
        return Result.OK("添加成功！");
    }

    @AutoLog(value = "编辑")
    @ApiOperation(value = "编辑", notes = "编辑")
    @PutMapping(value = "/edit")
    public Result<?> edit(@RequestBody VeStudentVo dto) {
        veBaseStudentService.insertOrUpdate(dto, false);
        return Result.OK("编辑成功!");
    }

    @AutoLog(value = "批量删除")
    @ApiOperation(value = "批量删除", notes = "批量删除")
    @DeleteMapping(value = "/deleteBatch")
    public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {

        LambdaQueryWrapper<VeBaseStudent> studentLambdaQueryWrapper = new LambdaQueryWrapper<>();
        studentLambdaQueryWrapper.in(VeBaseStudent::getId, Arrays.asList(ids.split(",")));
        List<String> strings = veBaseStudentService.listByWrapper(studentLambdaQueryWrapper).stream().map(VeBaseStudent::getUserId).collect(Collectors.toList());
        if (strings.size() > 0) {
            for (String userId : strings) {
                veBaseAppUserService.deleteAppUser(userId);
            }
        }
        veBaseStudentService.delete(Arrays.asList(ids.split(",")));
        veBaseStudentInfoService.delete(Arrays.asList(ids.split(",")));
        return Result.OK("批量删除成功!");
    }


    @AutoLog(value = "更新状态")
    @ApiOperation(value = "更新状态")
    @PostMapping(value = "/updateStatus")
    public Result<?> updateStatus(@RequestBody StatusDto statusDto) {
        UpdateWrapper<VeBaseStudent> updateWrapper = new UpdateWrapper<>();
        if (statusDto.getIds() != null && statusDto.getIds().size() > 0) {
            updateWrapper.set("status", statusDto.getStatus());
            updateWrapper.in("id", statusDto.getIds());
            veBaseStudentService.update(updateWrapper);
            return Result.OK("批量更新成功!");
        } else {
            return Result.error("未选择!");
        }
    }


    /**
     * 查询家庭成员
     */
    @ApiOperation("查询家庭成员")
    @GetMapping("/findFamilys")
    public Result<?> findFamilys(String stuId) {
        LambdaQueryWrapper<VeStuFamily> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(VeStuFamily::getStuId, stuId);
        List<VeStuFamily> list = veStuFamilyService.listByWrapper(queryWrapper);
        return Result.OK(list);
    }


    @ApiOperation(value = "查询通过ID")
    @GetMapping(value = "/findByIds")
    public Result<?> findByIds(@RequestParam(name = "ids", required = true) String ids) {
        LambdaQueryWrapper<VeBaseStudent> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(VeBaseStudent::getId, Arrays.asList(ids.split(",")));
        return Result.OK(veBaseStudentService.listByWrapper(wrapper));
    }

    /**
     * 导出excel
     *
     * @param request
     */
//    @RequestMapping(value = "/exportXls")
    @RequestMapping(value = "/export")
    public ModelAndView exportXls(@RequestBody PageDto<VeBaseStudent> page, HttpServletRequest request) throws IOException {
        List<VeXueJiExportDto> veXueJiExportDtoList = new ArrayList<>();
        // Step.1 组装查询条件
//        QueryWrapper<VeBaseStudent> queryWrapper = QueryGenerator.initQueryWrapper(veBaseStudent, request.getParameterMap());
        QueryWrapper<VeBaseStudent> queryWrapper = page.buildQueryWrapper(VeBaseStudent.class);
        //Step.2 AutoPoi 导出Excel
        ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
//        List<VeBaseStudent> pageList = new ArrayList<VeBaseStudent>();
        List<VeBaseStudent> veBaseStudentList = veBaseStudentService.listByWrapper(queryWrapper);

        //加载字典数据
        dictModelListMap = queryDictMap(false);
        if (veBaseStudentList.size() > 0) {
            veXueJiExportDtoList = veBaseStudentList.parallelStream()
                    .map(student -> {
                        VeXueJiExportDto dto = buildXueJiExcelDto(student);
                        return dto;
                    })
                    .collect(Collectors.toList());
        }
        //数据排序
        veXueJiExportDtoList.sort(
                Comparator.comparing(VeXueJiExportDto::getGrade, Comparator.nullsFirst(Comparator.naturalOrder()))
                        .thenComparing(VeXueJiExportDto::getFal, Comparator.nullsFirst(Comparator.naturalOrder()))
                        .thenComparing(VeXueJiExportDto::getSpec, Comparator.nullsFirst(Comparator.naturalOrder()))
                        .thenComparing(VeXueJiExportDto::getBj, Comparator.nullsLast(Comparator.naturalOrder()))
        );
        Integer sortNum = 1;
        for (VeXueJiExportDto dto : veXueJiExportDtoList) {
            dto.setSortNum(sortNum++);
        }
        // 导出文件名称
        mv.addObject(NormalExcelConstants.FILE_NAME, "学籍信息");
        // 注解对象Class
        mv.addObject(NormalExcelConstants.CLASS, VeXueJiExportDto.class);
        // 自定义表格参数
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("学籍信息列表", "导出人:" + user.getRealname(), "学籍信息"));
        // 导出数据列表
        mv.addObject(NormalExcelConstants.DATA_LIST, veXueJiExportDtoList);
        return mv;
//        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
//        response.setHeader("Content-Disposition",  "attachment; filename=学籍信息.xlsx");
//        EasyExcel.write(response.getOutputStream(),  VeXueJiExportDto.class)
//                .sheet("学籍信息")
//                .doWrite(veXueJiExportDtoList);
    }

    private Map<String, List<DictModel>> queryDictMap(Boolean isNoDict) {
        Map<String, List<DictModel>> map = new HashMap();
        if (!isNoDict) {
            List<DictModel> YWXJ = iSysBaseAPI.queryDictItemsByCode("YWXJ");
            map.put("YWXJ", YWXJ);
            List<DictModel> SFZX = iSysBaseAPI.queryDictItemsByCode("SFZX");
            map.put("SFZX", SFZX);
            List<DictModel> sex = iSysBaseAPI.queryDictItemsByCode("sex");
            map.put("sex", sex);
            List<DictModel> SFZJLXM = iSysBaseAPI.queryDictItemsByCode("SFZJLXM");
            map.put("SFZJLXM", SFZJLXM);
            List<DictModel> nation = iSysBaseAPI.queryDictItemsByCode("nation");
            map.put("nation", nation);
            List<DictModel> RXWHCD = iSysBaseAPI.queryDictItemsByCode("RXWHCD");
            map.put("RXWHCD", RXWHCD);
            List<DictModel> XSLB = iSysBaseAPI.queryDictItemsByCode("XSLB");
            map.put("XSLB", XSLB);
            List<DictModel> XXXS = iSysBaseAPI.queryDictItemsByCode("XXXS");
            map.put("XXXS", XXXS);
            List<DictModel> JDFS = iSysBaseAPI.queryDictItemsByCode("JDFS");
            map.put("JDFS", JDFS);
            List<DictModel> GATQWM = iSysBaseAPI.queryDictItemsByCode("GATQWM");
            map.put("GATQWM", GATQWM);
            List<DictModel> ZZMMM = iSysBaseAPI.queryDictItemsByCode("ZZMMM");
            map.put("ZZMMM", ZZMMM);
            List<DictModel> healthy = iSysBaseAPI.queryDictItemsByCode("healthy");
            map.put("healthy", healthy);
            List<DictModel> ZSFS = iSysBaseAPI.queryDictItemsByCode("ZSFS");
            map.put("ZSFS", ZSFS);
            List<DictModel> HKSZ = iSysBaseAPI.queryDictItemsByCode("HKSZ");
            map.put("HKSZ", HKSZ);
            List<DictModel> residence = iSysBaseAPI.queryDictItemsByCode("residence");
            map.put("residence", residence);
            List<DictModel> RXFS = iSysBaseAPI.queryDictItemsByCode("RXFS");
            map.put("RXFS", RXFS);
            List<DictModel> SFSQZN = iSysBaseAPI.queryDictItemsByCode("SFSQZN");
            map.put("SFSQZN", SFSQZN);
            List<DictModel> SFJDLK = iSysBaseAPI.queryDictItemsByCode("SFJDLK");
            map.put("SFJDLK", SFJDLK);
            List<DictModel> SFDB = iSysBaseAPI.queryDictItemsByCode("SFDB");
            map.put("SFDB", SFDB);
            List<DictModel> SFSSGJZXJ = iSysBaseAPI.queryDictItemsByCode("SFSSGJZXJ");
            map.put("SFSSGJZXJ", SFSSGJZXJ);
            List<DictModel> GXM = iSysBaseAPI.queryDictItemsByCode("GXM");
            map.put("GXM", GXM);
            List<DictModel> SFJHR = iSysBaseAPI.queryDictItemsByCode("SFJHR");
            map.put("SFJHR", SFJHR);
            List<DictModel> JTLB = iSysBaseAPI.queryDictItemsByCode("JTLB");
            map.put("JTLB", JTLB);
            List<DictModel> XX = iSysBaseAPI.queryDictItemsByCode("XX");
            map.put("XX", XX);
        }

        //表数据字典

        List<DictModel> ve_base_xuezi = iSysBaseAPI.queryTableDictItemsByCode("ve_base_xuezi", "XZMC", "id");
        map.put("ve_base_xuezi", ve_base_xuezi);
        List<DictModel> ve_base_banji = iSysBaseAPI.queryTableDictItemsByCode("ve_base_banji", "XZBDM", "id");
        map.put("ve_base_banji", ve_base_banji);
        List<DictModel> ve_base_specialty = iSysBaseAPI.queryTableDictItemsByCode("ve_base_specialty", "ZYMC", "id");
        map.put("ve_base_specialty", ve_base_specialty);
        List<DictModel> ve_base_faculty = iSysBaseAPI.queryTableDictItemsByCode("ve_base_faculty", "YXMC", "id");
        map.put("ve_base_faculty", ve_base_faculty);
        List<DictModel> ve_base_grade = iSysBaseAPI.queryTableDictItemsByCode("ve_base_grade", "njdm", "id");
        map.put("ve_base_grade", ve_base_grade);

        //地区表字典数据
        List<DictModel> ve_base_dict_area = iSysBaseAPI.queryTableDictItemsByCode("ve_base_dict_area", "name", "id");
        map.put("ve_base_dict_area", ve_base_dict_area);
        return map;
    }

    private VeXueJiExportDto buildXueJiExcelDto(VeBaseStudent veBaseStudent) {
        VeXueJiExportDto veXueJiExportDto = new VeXueJiExportDto();
        BeanUtils.copyProperties(veBaseStudent, veXueJiExportDto);
        veXueJiExportDto.setGrade(veBaseStudent.getGradeId() == null ? "" : veBaseStudent.getGradeId().toString());
        veXueJiExportDto.setFal(veBaseStudent.getFalId() == null ? "" : veBaseStudent.getFalId().toString());
        veXueJiExportDto.setSpec(veBaseStudent.getSpecId() == null ? "" : veBaseStudent.getSpecId().toString());
        veXueJiExportDto.setBj(veBaseStudent.getBjId() == null ? "" : veBaseStudent.getBjId().toString());
        veXueJiExportDto.setXz(veBaseStudent.getXz() == null ? "" : veBaseStudent.getXz().toString());
        veXueJiExportDto.setRxrq(veBaseStudent.getRxrq() == null ? "" : veBaseStudent.getRxrq().toString());
        veXueJiExportDto.setJdfs(veBaseStudent.getJdfs() == null ? "" : veBaseStudent.getJdfs().toString());
        //查询学生详细信息
        VeBaseStudentInfo veBaseStudentInfo = veBaseStudentInfoService.findDtoByStuId(veBaseStudent.getId() == null ? "" : veBaseStudent.getId().toString());
        if (veBaseStudentInfo != null) {
            BeanUtils.copyProperties(veBaseStudentInfo, veXueJiExportDto);
            veXueJiExportDto.setCsrq(veBaseStudentInfo.getCsrq() == null ? "" : veBaseStudentInfo.getCsrq().toString());
            veXueJiExportDto.setLqzy(veBaseStudentInfo.getLqzyText());
            veXueJiExportDto.setSfdb(veBaseStudentInfo.getSfdb() == null ? "" : veBaseStudentInfo.getSfdb().toString());
        }

        //查询家庭信息
        LambdaQueryWrapper<VeStuFamily> stuFamilyLambdaQueryWrapper = new LambdaQueryWrapper<>();
        stuFamilyLambdaQueryWrapper.eq(VeStuFamily::getStuId, veBaseStudent.getId() + "");
        stuFamilyLambdaQueryWrapper.orderByDesc(VeStuFamily::getSfjhr);
        stuFamilyLambdaQueryWrapper.last("limit 2");
        List<VeStuFamily> veStuFamilyList = veStuFamilyService.listByWrapper(stuFamilyLambdaQueryWrapper);
        if (veStuFamilyList != null && veStuFamilyList.size() > 0) {
            veXueJiExportDto.setName1(veStuFamilyList.get(0).getName());
            veXueJiExportDto.setGxm1(veStuFamilyList.get(0).getGxm());
            veXueJiExportDto.setPhone1(veStuFamilyList.get(0).getPhone());
            veXueJiExportDto.setSfzjh1(veStuFamilyList.get(0).getSfzjh());
            veXueJiExportDto.setSfzjlxm1(veStuFamilyList.get(0).getSfzjlxm());
            veXueJiExportDto.setSfjhr1(veStuFamilyList.get(0).getSfjhr());
            veXueJiExportDto.setJtlb(veStuFamilyList.get(0).getJtlb());
            if (veStuFamilyList.size() > 1) {
                veXueJiExportDto.setName2(veStuFamilyList.get(1).getName());
                veXueJiExportDto.setGxm2(veStuFamilyList.get(1).getGxm());
                veXueJiExportDto.setPhone2(veStuFamilyList.get(1).getPhone());
                veXueJiExportDto.setSfzjh2(veStuFamilyList.get(1).getSfzjh());
                veXueJiExportDto.setSfzjlxm2(veStuFamilyList.get(1).getSfzjlxm());
                veXueJiExportDto.setSfjhr2(veStuFamilyList.get(1).getSfjhr());
            }

        }
        //字典值转换
        translateDict(veXueJiExportDto);
        //表字典转换
        translateDictFromTable(veXueJiExportDto);
        //时间转换
        translateTime(veXueJiExportDto);

        return veXueJiExportDto;
    }

    //表字典转换id转名称
    public void translateDictFromTable(VeXueJiExportDto veXueJiExportDto) {
        if (veXueJiExportDto.getGrade() != null) {
            String dict = returnDictText("ve_base_grade", veXueJiExportDto.getGrade());
            veXueJiExportDto.setGrade(dict);
        }
        if (veXueJiExportDto.getFal() != null) {
            String dict = returnDictText("ve_base_faculty", veXueJiExportDto.getFal());
            veXueJiExportDto.setFal(dict);
        }
        if (veXueJiExportDto.getSpec() != null) {
            String dict = returnDictText("ve_base_specialty", veXueJiExportDto.getSpec());
            veXueJiExportDto.setSpec(dict);
        }

        if (veXueJiExportDto.getBj() != null) {
            String dict = returnDictText("ve_base_banji", veXueJiExportDto.getBj());
            veXueJiExportDto.setBj(dict);
        }
        if (veXueJiExportDto.getXz() != null) {
            String dict = returnDictText("ve_base_xuezi", veXueJiExportDto.getXz());
            veXueJiExportDto.setXz(dict);
        }


    }

    //字典值转换
    public void translateDict(VeXueJiExportDto veXueJiExportDto) {
        if (StringUtils.isNotBlank(veXueJiExportDto.getYwxj())) {
            String ywxj = returnDictText("YWXJ", veXueJiExportDto.getYwxj());
            veXueJiExportDto.setYwxj(ywxj);
        }
        if (veXueJiExportDto.getSfzx() != null) {
            String sfzx = returnDictText("SFZX", veXueJiExportDto.getSfzx());
            veXueJiExportDto.setSfzx(sfzx);
        }
        if (veXueJiExportDto.getXbm() != null) {
            String sex = returnDictText("sex", veXueJiExportDto.getXbm());
            veXueJiExportDto.setXbm(sex);
        }
        if (veXueJiExportDto.getSfzjlxm() != null) {
            String sfzjlxm = returnDictText("SFZJLXM", veXueJiExportDto.getSfzjlxm());
            veXueJiExportDto.setSfzjlxm(sfzjlxm);
        }
        if (veXueJiExportDto.getMzm() != null) {
            String mzm = returnDictText("nation", veXueJiExportDto.getMzm());
            veXueJiExportDto.setMzm(mzm);
        }
        if (veXueJiExportDto.getRxwhcd() != null) {
            String rxwhcd = returnDictText("RXWHCD", veXueJiExportDto.getRxwhcd());
            veXueJiExportDto.setRxwhcd(rxwhcd);
        }
        if (veXueJiExportDto.getXslb() != null) {
            String xslb = returnDictText("XSLB", veXueJiExportDto.getXslb());
            veXueJiExportDto.setXslb(xslb);
        }
        if (veXueJiExportDto.getXxxs() != null) {
            String xxxs = returnDictText("XXXS", veXueJiExportDto.getXxxs());
            veXueJiExportDto.setXxxs(xxxs);
        }
        if (veXueJiExportDto.getJdfs() != null) {
            String jdfs = returnDictText("JDFS", veXueJiExportDto.getJdfs());
            veXueJiExportDto.setJdfs(jdfs);
        }
        if (veXueJiExportDto.getGatqwm() != null) {
            String gatqwm = returnDictText("GATQWM", veXueJiExportDto.getGatqwm());
            veXueJiExportDto.setGatqwm(gatqwm);
        }
        if (veXueJiExportDto.getZzmmm() != null) {
            String zzmmm = returnDictText("ZZMMM", veXueJiExportDto.getZzmmm());
            veXueJiExportDto.setZzmmm(zzmmm);
        }
        if (veXueJiExportDto.getJkzkm() != null) {
            String healthy = returnDictText("healthy", veXueJiExportDto.getJkzkm());
            veXueJiExportDto.setJkzkm(healthy);
        }
        if (veXueJiExportDto.getZsfs() != null) {
            String zsfs = returnDictText("ZSFS", veXueJiExportDto.getZsfs());
            veXueJiExportDto.setZsfs(zsfs);
        }
        if (veXueJiExportDto.getHksz() != null) {
            String hksz = returnDictText("HKSZ", veXueJiExportDto.getHksz());
            veXueJiExportDto.setHksz(hksz);
        }
//        居住地类型
        if (veXueJiExportDto.getHklbm() != null) {
            String residence = returnDictText("residence", veXueJiExportDto.getHklbm());
            veXueJiExportDto.setHklbm(residence);
        }
        if (veXueJiExportDto.getRxfs() != null) {
            String rxfs = returnDictText("RXFS", veXueJiExportDto.getRxfs());
            veXueJiExportDto.setRxfs(rxfs);
        }
        if (veXueJiExportDto.getSfsqzn() != null) {
            String sfsqzn = returnDictText("SFSQZN", veXueJiExportDto.getSfsqzn());
            veXueJiExportDto.setSfsqzn(sfsqzn);
        }
        if (veXueJiExportDto.getSfjdlk() != null) {
            String sfjdlk = returnDictText("SFJDLK", veXueJiExportDto.getSfjdlk());
            veXueJiExportDto.setSfjdlk(sfjdlk);
        }
        if (veXueJiExportDto.getSfdb() != null) {
            String sfdb = returnDictText("SFDB", veXueJiExportDto.getSfdb());
            veXueJiExportDto.setSfdb(sfdb);
        }
        if (veXueJiExportDto.getSfssgjzxj() != null) {
            String sfssgjzxj = returnDictText("SFSSGJZXJ", veXueJiExportDto.getSfssgjzxj());
            veXueJiExportDto.setSfssgjzxj(sfssgjzxj);
        }
        if (veXueJiExportDto.getGxm1() != null) {
            String gxm = returnDictText("GXM", veXueJiExportDto.getGxm1());
            veXueJiExportDto.setGxm1(gxm);
        }
        if (veXueJiExportDto.getSfjhr1() != null) {
            String sfjhr = returnDictText("SFJHR", veXueJiExportDto.getSfjhr1());
            veXueJiExportDto.setSfjhr1(sfjhr);
        }
        if (veXueJiExportDto.getSfzjlxm1() != null) {
            String sfzjlxm = returnDictText("SFZJLXM", veXueJiExportDto.getSfzjlxm1());
            veXueJiExportDto.setSfzjlxm1(sfzjlxm);
        }
        if (veXueJiExportDto.getGxm2() != null) {
            String gxm = returnDictText("GXM", veXueJiExportDto.getGxm2());
            veXueJiExportDto.setGxm2(gxm);
        }
        if (veXueJiExportDto.getSfjhr2() != null) {
            String sfjhr = returnDictText("SFJHR", veXueJiExportDto.getSfjhr2());
            veXueJiExportDto.setSfjhr2(sfjhr);
        }
        if (veXueJiExportDto.getSfzjlxm2() != null) {
            String sfzjlxm = returnDictText("SFZJLXM", veXueJiExportDto.getSfzjlxm2());
            veXueJiExportDto.setSfzjlxm2(sfzjlxm);
        }

        if (veXueJiExportDto.getJtlb() != null) {
            String jtlb = returnDictText("JTLB", veXueJiExportDto.getJtlb());
            veXueJiExportDto.setJtlb(jtlb);
        }
        if (veXueJiExportDto.getXx() != null) {
            String xx = returnDictText("XX", veXueJiExportDto.getXx());
            veXueJiExportDto.setXx(xx);
        }
    }

    /**
     * 时间转换
     */
    public void translateTime(VeXueJiExportDto veXueJiExportDto) {
        if (StringUtils.isNotBlank(veXueJiExportDto.getCsrq())) {
            String rxrq = DateTimeUtil.timestampToDate(Long.parseLong(veXueJiExportDto.getCsrq()));
            veXueJiExportDto.setCsrq(rxrq);
        }
        if (StringUtils.isNotBlank(veXueJiExportDto.getRxrq())) {
            String rxrq = DateTimeUtil.timestampToDate(Long.parseLong(veXueJiExportDto.getRxrq()));
            veXueJiExportDto.setRxrq(rxrq);
        }
    }

    /**
     * 导出模板
     *
     * @param request
     */
    @RequestMapping(value = "/exportTemp")
    public ModelAndView exportTemp(HttpServletRequest request) {
        //Step.2 AutoPoi 导出Excel
        ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
        List<VeXueJiExportDto> xueJiExcelDtos = new ArrayList<>();

        // 导出文件名称
        mv.addObject(NormalExcelConstants.FILE_NAME, "学籍信息模板");
        // 注解对象Class
        mv.addObject(NormalExcelConstants.CLASS, VeXueJiExportDto.class);
        // 自定义表格参数
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("学籍信息列表", "导出人:" + user.getRealname(), "学籍信息"));
        // 导出数据列表
        mv.addObject(NormalExcelConstants.DATA_LIST, xueJiExcelDtos);
        return mv;
    }

    /**
     * 导入文档直接传字典值版
     **/
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importDataNoDictReverse(MultipartHttpServletRequest request) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        //加载字典数据
        dictModelListMap = queryDictMap(true);

        return fileMap.values().stream()
                .map(file -> {
                    try (InputStream is = file.getInputStream()) {

                        List<VeXueJiExcelDto> list = ExcelUtils.importExcel(file, VeXueJiExcelDto.class);

                        /** // 1. 解析Excel数据并获取行号元数据
                         ImportParams params = new ImportParams();
                         params.setTitleRows(2);
                         params.setHeadRows(1);
                         params.setNeedSave(true);

                         //update-begin-author:wangshuai date:20201030 for:导入测试用例
                         boolean aBoolean = FieldPresenceUtil.fieldPresence(file.getInputStream(), VeXueJiExcelDto.class, params);
                         if (!aBoolean) {
                         throw new RuntimeException("导入Excel标题格式不匹配！");
                         }
                         //update-end-author:wangshuai date:20201030 for:导入测试用例
                         List<VeXueJiExcelDto> list = ExcelImportUtil.importExcel(file.getInputStream(), VeXueJiExcelDto.class, params);
                         */

                        if (list.size() > 5000) {
                            throw new RuntimeException("文档数据超出5000条");
                        }
                        OptimizedExcelValidator.validateVeXueJiData(list);

                        // 2. 双重身份证校验
                        // 2.1 本地数据重复性校验
                        Map<String, List<VeXueJiExcelDto>> localSfzhGroups = list.stream()
                                .collect(Collectors.groupingBy(VeXueJiExcelDto::getSfzh));
                        List<String> localDuplicates = localSfzhGroups.entrySet().stream()
                                .filter(e -> e.getValue().size() > 1)
                                .map(e -> String.format(" 身份证[%s]在序号%s行重复",
                                        e.getKey(),
                                        e.getValue().stream()
                                                .map(dto -> String.valueOf(dto.getSortNum()))
                                                .collect(Collectors.joining(","))))
                                .collect(Collectors.toList());
                        if (!localDuplicates.isEmpty()) {
                            throw new RuntimeException("本地数据重复: " + String.join(";  ", localDuplicates));
                        }

                        // 2.2 预加载数据库存在的身份证号
                        Set<String> allSfzh = localSfzhGroups.keySet();
                        Map<String, Integer> sfzhToIdMap = veBaseStudentService.batchGetIdBySfzh(allSfzh);
                        // ================ 新增学号校验逻辑 ================ //
                        // 2.3 学号本地重复性校验
                        Map<String, List<VeXueJiExcelDto>> localXhGroups = list.stream()
                                .filter(dto -> StringUtils.isNotBlank(dto.getXh()))  // 过滤空学号
                                .collect(Collectors.groupingBy(VeXueJiExcelDto::getXh));

                        List<String> xhDuplicates = localXhGroups.entrySet().stream()
                                .filter(e -> e.getValue().size() > 1)
                                .map(e -> String.format(" 学号[%s]在序号%s行重复",
                                        e.getKey(),
                                        e.getValue().stream()
                                                .map(dto -> String.valueOf(dto.getSortNum()))
                                                .collect(Collectors.joining(","))))
                                .collect(Collectors.toList());
                        if (!xhDuplicates.isEmpty()) {
                            throw new RuntimeException("本地学号重复: " + String.join(";  ", xhDuplicates));
                        }

                        // 2.4 预加载数据库存在的学号
                        Map<String, Integer> existingXh = veBaseStudentService.batchGetXhByNumbers(localXhGroups.keySet());

                        // 3. 并行处理数据
                        ConcurrentLinkedQueue<String> errorMessage = new ConcurrentLinkedQueue<>();
                        AtomicInteger successLines = new AtomicInteger(0);
                        AtomicInteger errorLines = new AtomicInteger(0);

                        list.stream().forEach(dto -> {
//                        for (VeXueJiExcelDto dto : list) {
                            try {
                                // 3.1 构建学生对象
                                VeBaseStudentDto student = buildVeBaseStudentDto(dto, true);
                                //判断学号是否重复
                                boolean isAdd = !existingXh.containsKey(student.getXh());
                                //判断身份证号是否重复
                                boolean sfzhRepeat = sfzhToIdMap.containsKey(student.getSfzh());
                                if (!isAdd) {
                                    if (sfzhRepeat) {
                                        if (!existingXh.get(student.getXh()).equals(sfzhToIdMap.get(student.getSfzh()))) {
                                            throw new RuntimeException("身份证号已关联其他学号");
                                        }
                                    }
                                    student.setId(existingXh.get(student.getXh()));
                                } else {
                                    if (sfzhRepeat) {
                                        throw new RuntimeException("身份证号已关联其他学号");
                                    }
                                }

                                // 3.2 执行插入/更新
                                VeStudentVo vo = new VeStudentVo();
                                vo.setStu(student);
                                vo.setStuInfo(buildVeBaseStudentInfoDto(dto, true));
                                if (StringUtils.isNotBlank(dto.getName1())) {
                                    vo.setFamily(buildVeStuFamilyDtoList(dto, true));
                                }
//                                        .setIsAdd(isAdd);
                                veBaseStudentService.insertOrUpdate(vo, isAdd);
                                successLines.incrementAndGet();
                            } catch (Exception e) {
                                errorLines.incrementAndGet();
                                errorMessage.add(formatError(dto, e));
                            }
//                        }

                        });

                        return ImportExcelUtil.imporReturnRes(errorLines.get(), successLines.get(), new ArrayList<>(errorMessage));
                    } catch (Exception e) {
                        log.error(" 导入失败: {}", e.getMessage(), e);
                        return Result.error(" 导入失败: " + e.getMessage().replaceAll("[\r\n]", " ")); // 防止换行符破坏响应格式
                    }
                })
                .findFirst()
                .orElse(Result.error(" 未上传有效文件"));
    }

    /**
     * 通过excel导入数据
     *
     * @param request
     * @param
     * @return
     */
    //@RequiresRoles({"admin"})
//    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 获取上传文件对象
            ImportParams params = new ImportParams();
            params.setTitleRows(2);
            params.setHeadRows(1);
            params.setNeedSave(true);
            try {
                //update-begin-author:wangshuai date:20201030 for:导入测试用例
                boolean aBoolean = FieldPresenceUtil.fieldPresence(file.getInputStream(), VeXueJiExcelDto.class, params);
                if (!aBoolean) {
                    throw new RuntimeException("导入Excel标题格式不匹配！");
                }
                //update-end-author:wangshuai date:20201030 for:导入测试用例
                List<VeXueJiExcelDto> list = ExcelImportUtil.importExcel(file.getInputStream(), VeXueJiExcelDto.class, params);
                if (list.size() > 5000) {
                    throw new RuntimeException("文档数据超出5000条");
                }
                // 错误信息
                List<String> errorMessage = new ArrayList<>();
                int successLines = 0, errorLines = 0;
                for (int i = 0; i < list.size(); i++) {
                    VeXueJiExcelDto veXueJiExcelDto = list.get(i);
                    VeStudentVo veStudentVo = new VeStudentVo();

                    try {
                        //保存学生基本信息
                        VeBaseStudentDto veBaseStudent = buildVeBaseStudentDto(veXueJiExcelDto, false);

//                    veBaseStudentService.save(veBaseStudent);
                        //保存学生详细信息
                        VeBaseStudentInfoDto veBaseStudentInfo = buildVeBaseStudentInfoDto(veXueJiExcelDto, false);

                        List<VeStuFamilyDto> veStuFamilyDtoList = new ArrayList<>();
                        if (StringUtils.isNotBlank(veXueJiExcelDto.getName1())) {
                            veStuFamilyDtoList = buildVeStuFamilyDtoList(veXueJiExcelDto, false);
                        }

                        boolean isAdd = true;
                        //判断是否已存在
                        LambdaQueryWrapper<VeBaseStudent> veBaseStudentLambdaQueryWrapper = new LambdaQueryWrapper<>();
                        veBaseStudentLambdaQueryWrapper.eq(VeBaseStudent::getSfzh, veBaseStudent.getSfzh());
                        List<VeBaseStudent> veBaseStudentList = veBaseStudentService.listByWrapper(veBaseStudentLambdaQueryWrapper);
                        if (veBaseStudentList.size() > 0) {
                            veBaseStudent.setId(veBaseStudentList.get(0).getId());
                            isAdd = false;
                        }
                        veStudentVo.setStu(veBaseStudent);
                        veStudentVo.setStuInfo(veBaseStudentInfo);
                        veStudentVo.setFamily(veStuFamilyDtoList);
                        //保存数据
                        veBaseStudentService.insertOrUpdate(veStudentVo, isAdd);
                        successLines++;
                    } catch (Exception e) {
                        errorLines++;
                        int lineNumber = i + 1;
                        errorMessage.add("第 " + lineNumber + " 行已忽略导入，" + e.getMessage());
                    }
                }
                return ImportExcelUtil.imporReturnRes(errorLines, successLines, errorMessage);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return Result.error("文件导入失败:" + e.getMessage());
            } finally {
                try {
                    file.getInputStream().close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return Result.error("文件导入失败！");
    }

    /**
     * 导入使用线程优化效率版
     **/
//    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importData(MultipartHttpServletRequest request) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        //加载字典数据
        dictModelListMap = queryDictMap(false);
        return fileMap.values().stream()
                .map(file -> {
                    try (InputStream is = file.getInputStream()) {
                        // 1. 解析Excel数据并获取行号元数据
                        ImportParams params = new ImportParams();
                        params.setTitleRows(2);
                        params.setHeadRows(1);
                        params.setNeedSave(true);
                        //update-begin-author:wangshuai date:20201030 for:导入测试用例
                        boolean aBoolean = FieldPresenceUtil.fieldPresence(file.getInputStream(), VeXueJiExcelDto.class, params);
                        if (!aBoolean) {
                            throw new RuntimeException("导入Excel标题格式不匹配！");
                        }
                        //update-end-author:wangshuai date:20201030 for:导入测试用例
                        List<VeXueJiExcelDto> list = ExcelImportUtil.importExcel(file.getInputStream(), VeXueJiExcelDto.class, params);

                        if (list.size() > 5000) {
                            throw new RuntimeException("文档数据超出5000条");
                        }

                        // 2. 双重身份证校验
                        // 2.1 本地数据重复性校验
                        Map<String, List<VeXueJiExcelDto>> localSfzhGroups = list.stream()
                                .collect(Collectors.groupingBy(VeXueJiExcelDto::getSfzh));
                        List<String> localDuplicates = localSfzhGroups.entrySet().stream()
                                .filter(e -> e.getValue().size() > 1)
                                .map(e -> String.format(" 身份证[%s]在序号%s行重复",
                                        e.getKey(),
                                        e.getValue().stream()
                                                .map(dto -> String.valueOf(dto.getSortNum()))
                                                .collect(Collectors.joining(","))))
                                .collect(Collectors.toList());
                        if (!localDuplicates.isEmpty()) {
                            throw new RuntimeException("本地数据重复: " + String.join(";  ", localDuplicates));
                        }

                        // 2.2 预加载数据库存在的身份证号
                        Set<String> allSfzh = localSfzhGroups.keySet();
                        Map<String, Integer> sfzhToIdMap = veBaseStudentService.batchGetIdBySfzh(allSfzh);
                        // ================ 新增学号校验逻辑 ================ //
                        // 2.3 学号本地重复性校验
                        Map<String, List<VeXueJiExcelDto>> localXhGroups = list.stream()
                                .filter(dto -> StringUtils.isNotBlank(dto.getXh()))  // 过滤空学号
                                .collect(Collectors.groupingBy(VeXueJiExcelDto::getXh));

                        List<String> xhDuplicates = localXhGroups.entrySet().stream()
                                .filter(e -> e.getValue().size() > 1)
                                .map(e -> String.format(" 学号[%s]在序号%s行重复",
                                        e.getKey(),
                                        e.getValue().stream()
                                                .map(dto -> String.valueOf(dto.getSortNum()))
                                                .collect(Collectors.joining(","))))
                                .collect(Collectors.toList());
                        if (!xhDuplicates.isEmpty()) {
                            throw new RuntimeException("本地学号重复: " + String.join(";  ", xhDuplicates));
                        }

                        // 2.4 预加载数据库存在的学号
                        Map<String, Integer> existingXh = veBaseStudentService.batchGetXhByNumbers(localXhGroups.keySet());

                        // 3. 并行处理数据
                        ConcurrentLinkedQueue<String> errorMessage = new ConcurrentLinkedQueue<>();
                        AtomicInteger successLines = new AtomicInteger(0);
                        AtomicInteger errorLines = new AtomicInteger(0);

                        list.parallelStream().forEach(dto -> {
//                        for (VeXueJiExcelDto dto : list) {
                            try {
                                // 3.1 构建学生对象
                                VeBaseStudentDto student = buildVeBaseStudentDto(dto, false);
                                //判断学号是否重复
                                boolean isAdd = !existingXh.containsKey(student.getXh());
                                //判断身份证号是否重复
                                boolean sfzhRepeat = sfzhToIdMap.containsKey(student.getSfzh());
                                if (!isAdd) {
                                    if (sfzhRepeat) {
                                        if (!existingXh.get(student.getXh()).equals(sfzhToIdMap.get(student.getSfzh()))) {
                                            throw new RuntimeException("身份证号已关联其他学号");
                                        }
                                    }
                                    student.setId(existingXh.get(student.getXh()));
                                } else {
                                    if (sfzhRepeat) {
                                        throw new RuntimeException("身份证号已关联其他学号");
                                    }
                                }

                                // 3.2 执行插入/更新
                                VeStudentVo vo = new VeStudentVo();
                                vo.setStu(student);
                                vo.setStuInfo(buildVeBaseStudentInfoDto(dto, false));
                                if (StringUtils.isNotBlank(dto.getName1())) {
                                    vo.setFamily(buildVeStuFamilyDtoList(dto, false));
                                }
//                                        .setIsAdd(isAdd);
                                veBaseStudentService.insertOrUpdate(vo, isAdd);
                                successLines.incrementAndGet();
                            } catch (Exception e) {
                                errorLines.incrementAndGet();
                                errorMessage.add(formatError(dto, e));
                            }
//                        }

                        });

                        return ImportExcelUtil.imporReturnRes(errorLines.get(), successLines.get(), new ArrayList<>(errorMessage));
                    } catch (Exception e) {
                        log.error(" 导入失败: {}", e.getMessage(), e);
                        return Result.error(" 导入失败: " + e.getMessage().replaceAll("[\r\n]", " ")); // 防止换行符破坏响应格式
                    }
                })
                .findFirst()
                .orElse(Result.error(" 未上传有效文件"));
    }

    /**
     * 错误信息格式化（含行号定位）
     */
    private String formatError(VeXueJiExcelDto dto, Exception e) {
        String cause = e.getCause() != null ? e.getCause().getMessage() : e.getMessage();
        return String.format(" 序号%d行错误: %s (身份证: %s)",
                dto.getSortNum(),  // Excel文档中的序号
                cause,
                dto.getSfzh());
    }


    /**
     * 构建导入用的学生信息
     */
    public VeBaseStudentDto buildVeBaseStudentDto(VeXueJiExcelDto veXueJiExcelDto, Boolean noDict) {
        VeBaseStudentDto veBaseStudentDto = new VeBaseStudentDto();
        BeanUtils.copyProperties(veXueJiExcelDto, veBaseStudentDto);

        //非空判断
        notNull(veXueJiExcelDto);
        //字典逆转换
        dictReverseForVeBaseStudentDto(veXueJiExcelDto, veBaseStudentDto, noDict);
        return veBaseStudentDto;
    }

    public void notNull(VeXueJiExcelDto veXueJiExcelDto) {
        if (StringUtils.isBlank(veXueJiExcelDto.getXh())) {
            throw new RuntimeException("请填写‘用户学号’");
        }
        if (StringUtils.isBlank(veXueJiExcelDto.getXm())) {
            throw new RuntimeException("请填写‘姓名’");
        }
        if (StringUtils.isBlank(veXueJiExcelDto.getSfzh())) {
            throw new RuntimeException("请填写‘身份证件号’");
        }
        if (StringUtils.isBlank(veXueJiExcelDto.getSfzjlxm())) {
            throw new RuntimeException("请填写‘身份证件类型’");
        }
        if (StringUtils.isBlank(veXueJiExcelDto.getFal())) {
            throw new RuntimeException("请填写‘系/部’");
        }
        if (StringUtils.isBlank(veXueJiExcelDto.getSpec())) {
            throw new RuntimeException("请填写‘专业名称’");
        }

    }

    /**
     * 构建导入用的学生详细信息
     */
    public VeBaseStudentInfoDto buildVeBaseStudentInfoDto(VeXueJiExcelDto veXueJiExcelDto, Boolean noDict) {
        VeBaseStudentInfoDto veBaseStudentInfoDto = new VeBaseStudentInfoDto();
        BeanUtils.copyProperties(veXueJiExcelDto, veBaseStudentInfoDto);
        //字典逆转换
        dictReverseForVeBaseStudentInfoDto(veXueJiExcelDto, veBaseStudentInfoDto, noDict);
        return veBaseStudentInfoDto;
    }

    /**
     * 构建导入用的学生家庭信息
     */
    public List<VeStuFamilyDto> buildVeStuFamilyDtoList(VeXueJiExcelDto veXueJiExcelDto, Boolean noDict) {
        List<VeStuFamilyDto> veStuFamilyDtoList = new ArrayList<>();
        //保存家庭信息1
        VeStuFamilyDto veStuFamily1 = new VeStuFamilyDto();

        veStuFamily1.setName(veXueJiExcelDto.getName1());
//        if (StringUtils.isBlank(veXueJiExcelDto.getGxm1())){
//            throw new RuntimeException("请填写‘成员1关系’");
//        }
        veStuFamily1.setGxm(veXueJiExcelDto.getGxm1());
//        if (StringUtils.isBlank(veXueJiExcelDto.getPhone1())){
//            throw new RuntimeException("请填写‘成员1联系电话’");
//        }
        veStuFamily1.setPhone(veXueJiExcelDto.getPhone1());
        veStuFamily1.setSfjhr(veXueJiExcelDto.getSfjhr1());
//        if (StringUtils.isBlank(veXueJiExcelDto.getSfzjh1())){
//            throw new RuntimeException("请填写‘成员1身份证件号’");
//        }
        veStuFamily1.setSfzjh(veXueJiExcelDto.getSfzjh1());
        veStuFamily1.setSfzjlxm(veXueJiExcelDto.getSfzjlxm1());
        veStuFamily1.setJtlb(veXueJiExcelDto.getJtlb());
//                    veStuFamilyService.save(veStuFamily1);
        System.out.println(veStuFamily1);
        veStuFamilyDtoList.add(veStuFamily1);

        //保存家庭信息2
        if (StringUtils.isNotBlank(veXueJiExcelDto.getName2())) {
            VeStuFamilyDto veStuFamily2 = new VeStuFamilyDto();
            veStuFamily2.setName(veXueJiExcelDto.getName2());

            veStuFamily2.setGxm(veXueJiExcelDto.getGxm2());
            veStuFamily2.setPhone(veXueJiExcelDto.getPhone2());
            veStuFamily2.setSfjhr(veXueJiExcelDto.getSfjhr2());

//        if (StringUtils.isBlank(veXueJiExcelDto.getSfzjh2())){
//            throw new RuntimeException("请填写‘成员2身份证件号’");
//        }
            veStuFamily2.setSfzjh(veXueJiExcelDto.getSfzjh2());
            veStuFamily2.setSfzjlxm(veXueJiExcelDto.getSfzjlxm2());
            veStuFamily2.setJtlb(veXueJiExcelDto.getJtlb());
//                    veStuFamilyService.save(veStuFamily2);
            System.out.println(veStuFamily2);
            veStuFamilyDtoList.add(veStuFamily2);
        }

        //字典逆转换
        if (!noDict) {
            dictReverseForVeStuFamilyDtoList(veXueJiExcelDto, veStuFamilyDtoList);
        }

        return veStuFamilyDtoList;
    }


    //学生信息字典逆转换,noDict为true则不转换字典数据，
    public void dictReverseForVeBaseStudentDto(VeXueJiExcelDto veXueJiExcelDto, VeBaseStudentDto veBaseStudentDto, Boolean noDict) {
        if (veXueJiExcelDto.getGrade() != null) {
            String dict = returnDictValue("ve_base_grade", veXueJiExcelDto.getGrade());
            if (dict != null) {
                veBaseStudentDto.setGradeId(Integer.parseInt(dict));
                veBaseStudentDto.setGradeText(veXueJiExcelDto.getGrade());
            } else {
                throw new RuntimeException("请填写正确的‘年级代码’");
            }

        }
        if (veXueJiExcelDto.getGrade() != null) {
            String dict = returnDictValue("ve_base_faculty", veXueJiExcelDto.getFal());
            if (dict != null) {
                veBaseStudentDto.setFalId(Integer.parseInt(dict));
                veBaseStudentDto.setFalText(veXueJiExcelDto.getFal());
            } else {
                throw new RuntimeException("请填写正确的‘学院名称’");
            }

        }
        if (veXueJiExcelDto.getSpec() != null) {
            String dict = returnDictValue("ve_base_specialty", veXueJiExcelDto.getSpec());
            if (dict != null) {
                veBaseStudentDto.setSpecId(Integer.parseInt(dict));
                veBaseStudentDto.setSpecText(veXueJiExcelDto.getSpec());
            } else {
                throw new RuntimeException("请填写正确的‘专业名称’");

            }
        }
        if (veXueJiExcelDto.getBj() != null) {
            String dict = returnDictValue("ve_base_banji", veXueJiExcelDto.getBj());
            if (dict != null) {
                veBaseStudentDto.setBjId(Integer.parseInt(dict));
                veBaseStudentDto.setBjText(veXueJiExcelDto.getBj());
            } else {
                throw new RuntimeException("请填写正确的‘班级代码’");
            }

        }
        if (veXueJiExcelDto.getXz() != null) {
            String dict = returnDictValue("ve_base_xuezi", veXueJiExcelDto.getXz());
            if (dict != null) {
                veBaseStudentDto.setXz(Integer.parseInt(dict));
            } else {
                throw new RuntimeException("请填写正确的‘学制名称’");
            }

        }

        if (StringUtils.isNotBlank(veXueJiExcelDto.getRxrq())) {
            try {
                Long td = Long.valueOf(DateTimeUtil.dateToTimestamp(veXueJiExcelDto.getRxrq()));
                if (td != null && td > 0) {
                    veBaseStudentDto.setRxrq(Integer.parseInt(td + ""));
                    veBaseStudentDto.setRxrqName(veXueJiExcelDto.getRxrq());
                } else {
                    throw new RuntimeException("请填写正确的‘入学日期’");
                }
            } catch (Exception e) {
                throw new RuntimeException("请填写正确的‘入学日期’");
            }
        }
        if (!noDict) {
            if (StringUtils.isNotBlank(veXueJiExcelDto.getYwxj())) {
                try {
                    String value = dictModelListMap.get("YWXJ").stream()
                            .filter(dict -> dict.getText().equals(veXueJiExcelDto.getYwxj()))
                            .map(DictModel::getValue).findFirst().get();

                    veBaseStudentDto.setYwxj(value);
                } catch (Exception e) {
                    throw new RuntimeException("请填写正确的‘学籍状态’");
                }

            }
            if (StringUtils.isNotBlank(veXueJiExcelDto.getSfzx())) {
                try {
                    String value = dictModelListMap.get("SFZX").stream()
                            .filter(dict -> dict.getText().equals(veXueJiExcelDto.getSfzx()))
                            .map(DictModel::getValue).findFirst().get();

                    veBaseStudentDto.setSfzx(value);
                } catch (Exception e) {
                    throw new RuntimeException("请填写正确的‘是否在校’");
                }
            }
            if (StringUtils.isNotBlank(veXueJiExcelDto.getXbm())) {
                try {
                    String value = dictModelListMap.get("sex").stream()
                            .filter(dict -> dict.getText().equals(veXueJiExcelDto.getXbm()))
                            .map(DictModel::getValue).findFirst().get();

                    veBaseStudentDto.setXbm(value);
                } catch (Exception e) {
                    throw new RuntimeException("请填写正确的‘性别’");
                }
            }
            if (StringUtils.isNotBlank(veXueJiExcelDto.getSfzjlxm())) {
                try {
                    String value = dictModelListMap.get("SFZJLXM").stream()
                            .filter(dict -> dict.getText().equals(veXueJiExcelDto.getSfzjlxm()))
                            .map(DictModel::getValue).findFirst().get();

                    veBaseStudentDto.setSfzjlxm(value);
                } catch (Exception e) {
                    throw new RuntimeException("请填写正确的‘身份证件类型’");
                }
            }
            if (StringUtils.isNotBlank(veXueJiExcelDto.getMzm())) {
                try {
                    String value = dictModelListMap.get("nation").stream()
                            .filter(dict -> dict.getText().equals(veXueJiExcelDto.getMzm()))
                            .map(DictModel::getValue).findFirst().get();

                    veBaseStudentDto.setMzm(value);
                } catch (Exception e) {
                    throw new RuntimeException("请填写正确的‘民族’");
                }
            }
            if (StringUtils.isNotBlank(veXueJiExcelDto.getRxwhcd())) {
                try {
                    String value = dictModelListMap.get("RXWHCD").stream()
                            .filter(dict -> dict.getText().equals(veXueJiExcelDto.getRxwhcd()))
                            .map(DictModel::getValue).findFirst().get();

                    veBaseStudentDto.setRxwhcd(value);
                } catch (Exception e) {
                    throw new RuntimeException("请填写正确的‘入学文化程度’");
                }
            }
            if (StringUtils.isNotBlank(veXueJiExcelDto.getXslb())) {
                try {
                    String value = dictModelListMap.get("XSLB").stream()
                            .filter(dict -> dict.getText().equals(veXueJiExcelDto.getXslb()))
                            .map(DictModel::getValue).findFirst().get();

                    veBaseStudentDto.setXslb(value);
                } catch (Exception e) {
                    throw new RuntimeException("请填写正确的‘学生类别’");
                }
            }
            if (StringUtils.isNotBlank(veXueJiExcelDto.getXxxs())) {
                try {
                    String value = dictModelListMap.get("XXXS").stream()
                            .filter(dict -> dict.getText().equals(veXueJiExcelDto.getXxxs()))
                            .map(DictModel::getValue).findFirst().get();

                    veBaseStudentDto.setXxxs(value);
                } catch (Exception e) {
                    throw new RuntimeException("请填写正确的‘学习形式’");
                }
            }
            if (StringUtils.isNotBlank(veXueJiExcelDto.getJdfs())) {
                try {
                    String value = dictModelListMap.get("JDFS").stream()
                            .filter(dict -> dict.getText().equals(veXueJiExcelDto.getJdfs()))
                            .map(DictModel::getValue).findFirst().get();

                    veBaseStudentDto.setJdfs(Integer.parseInt(value));
                } catch (Exception e) {
                    throw new RuntimeException("请填写正确的‘就读方式’");
                }
            }
            if (StringUtils.isNotBlank(veXueJiExcelDto.getGatqwm()) && !veXueJiExcelDto.getGatqwm().trim().equals("无")) {
                try {
                    String value = dictModelListMap.get("GATQWM").stream()
                            .filter(dict -> dict.getText().equals(veXueJiExcelDto.getGatqwm()))
                            .map(DictModel::getValue).findFirst().get();

                    veBaseStudentDto.setGatqwm(value);
                } catch (Exception e) {
                    throw new RuntimeException("请填写正确的‘港澳台侨外’");
                }
            }
            if (StringUtils.isNotBlank(veXueJiExcelDto.getHksz())) {
                try {
                    String value = dictModelListMap.get("HKSZ").stream()
                            .filter(dict -> dict.getText().equals(veXueJiExcelDto.getHksz()))
                            .map(DictModel::getValue).findFirst().get();

                    veBaseStudentDto.setHksz(value);
                } catch (Exception e) {
                    throw new RuntimeException("请填写正确的‘户口性质’");
                }
            }
            if (StringUtils.isNotBlank(veXueJiExcelDto.getRxfs())) {
                try {

                    String value = dictModelListMap.get("RXFS").stream()
                            .filter(dict -> dict.getText().equals(veXueJiExcelDto.getRxfs()))
                            .map(DictModel::getValue).findFirst().get();

                    veBaseStudentDto.setRxfs(value);
                } catch (Exception e) {
                    throw new RuntimeException("请填写正确的‘入学方式’");
                }
            }
        }


        if (StringUtils.isNotBlank(veXueJiExcelDto.getSheng())) {
            Integer dict = dictReverseForArea(veXueJiExcelDto.getSheng(), 0);
            if (dict != null) {
                veBaseStudentDto.setShengId(dict);
                veBaseStudentDto.setSheng(veXueJiExcelDto.getSheng());
            } else {
                throw new RuntimeException("请填写正确的‘生源所在省’");
            }
        }
        if (StringUtils.isNotBlank(veXueJiExcelDto.getShi())) {
            if (veBaseStudentDto.getShengId() == null) {
                throw new RuntimeException("请填写正确的‘生源所在省’");
            }
            Integer dict = dictReverseForArea(veXueJiExcelDto.getShi(), veBaseStudentDto.getShengId());
            if (dict != null) {
                veBaseStudentDto.setShiId(dict);
                veBaseStudentDto.setShi(veXueJiExcelDto.getShi());
            } else {
                throw new RuntimeException("请填写正确的‘生源所在市’");
            }
        }
        if (StringUtils.isNotBlank(veXueJiExcelDto.getQu())) {
            if (veBaseStudentDto.getShiId() == null) {
                throw new RuntimeException("请填写正确的‘生源所在市’");
            }
            Integer dict = dictReverseForArea(veXueJiExcelDto.getQu(), veBaseStudentDto.getShiId());
            if (dict != null) {
                veBaseStudentDto.setQuId(dict);
                veBaseStudentDto.setQu(veXueJiExcelDto.getQu());
            } else {
                throw new RuntimeException("请填写正确的‘生源所在区县’");
            }
        }
        //户口所在省市区
        if (StringUtils.isNotBlank(veXueJiExcelDto.getProvince())) {
            Integer dict = dictReverseForArea(veXueJiExcelDto.getProvince(), 0);
            if (dict != null) {
                veBaseStudentDto.setProvinceId(dict);
                veBaseStudentDto.setProvince(veXueJiExcelDto.getProvince());
            } else {
                throw new RuntimeException("请填写正确的‘户口所在省’");
            }
        }
        if (StringUtils.isNotBlank(veXueJiExcelDto.getCity())) {
            if (veBaseStudentDto.getProvinceId() == null) {
                throw new RuntimeException("请填写正确的‘户口所在省’");
            }
            Integer dict = dictReverseForArea(veXueJiExcelDto.getCity(), veBaseStudentDto.getProvinceId());
            if (dict != null) {
                veBaseStudentDto.setCityId(dict);
                veBaseStudentDto.setCity(veXueJiExcelDto.getCity());
            } else {
                throw new RuntimeException("请填写正确的‘户口所在市’");
            }
        }
        if (StringUtils.isNotBlank(veXueJiExcelDto.getCounty())) {
            if (veBaseStudentDto.getCityId() == null) {
                throw new RuntimeException("请填写正确的‘户口所在市’");
            }
            Integer shiId = dictReverseForArea(veXueJiExcelDto.getCounty(), veBaseStudentDto.getCityId());
            if (shiId != null) {
                veBaseStudentDto.setCountyId(shiId);
                veBaseStudentDto.setCounty(veXueJiExcelDto.getCounty());
            } else {
                throw new RuntimeException("请填写正确的‘户口所在区县’");
            }
        }

    }

    /***地区字典逆转换*/
    public Integer dictReverseForArea(String areaName, Integer pid) {
//        List<DictModel> dictModelList = iSysBaseAPI.queryFilterTableDictInfo("ve_base_dict_area", "id", "name",
//                " pid = " + pid  );
//        if (dictModelList != null && dictModelList.size() > 0) {
//            for (DictModel dictModel : dictModelList) {
//                if (dictModel.getValue().contains(areaName)&&dictModel.getPid().equals(pid)) {
//                    return Integer.parseInt(dictModel.getText());
//                }
//            }
//            return null;
//        } else {
//            return null;
//        }
        List<DictModel> dictModelList = dictModelListMap.get("ve_base_dict_area");

        return Optional.ofNullable(dictModelList)
                .orElseGet(Collections::emptyList)
                .stream()
                .filter(dictModel ->
                        dictModel.getText().contains(areaName) &&
                                pid.equals(dictModel.getPid()))
                .findFirst()
                .map(dictModel -> Integer.parseInt(dictModel.getValue()))
                .orElse(null);

    }

    /**
     * 学生详细字典逆转换 noDict为true则文档直接传递字典值，无需字典逆转换
     */
    public void dictReverseForVeBaseStudentInfoDto(VeXueJiExcelDto veXueJiExcelDto, VeBaseStudentInfoDto veBaseStudentInfoDto, Boolean noDict) {
        if (!noDict) {
            if (veXueJiExcelDto.getZzmmm() != null) {
                try {
                    String value = dictModelListMap.get("ZZMMM").stream()
                            .filter(dict -> dict.getText().equals(veXueJiExcelDto.getZzmmm()))
                            .map(DictModel::getValue).findFirst().get();
                    veBaseStudentInfoDto.setZzmmm(value);
                } catch (Exception e) {
                    throw new RuntimeException("请填写正确的‘政治面貌’");
                }
            }
            if (veXueJiExcelDto.getJkzkm() != null) {
                try {
                    String value = dictModelListMap.get("healthy").stream()
                            .filter(dict -> dict.getText().equals(veXueJiExcelDto.getJkzkm()))
                            .map(DictModel::getValue).findFirst().get();
                    veBaseStudentInfoDto.setJkzkm(value);
                } catch (Exception e) {
                    throw new RuntimeException("请填写正确的‘健康状况’");
                }
            }
            //居住地类型
            if (veXueJiExcelDto.getHklbm() != null) {
                try {
                    String value = dictModelListMap.get("residence").stream()
                            .filter(dict -> dict.getText().equals(veXueJiExcelDto.getHklbm()))
                            .map(DictModel::getValue).findFirst().get();
                    veBaseStudentInfoDto.setHklbm(value);
                } catch (Exception e) {
                    throw new RuntimeException("请填写正确的‘户口类别’");
                }
            }
            if (veXueJiExcelDto.getSfsqzn() != null) {
                try {
                    String value = dictModelListMap.get("SFSQZN").stream()
                            .filter(dict -> dict.getText().equals(veXueJiExcelDto.getSfsqzn()))
                            .map(DictModel::getValue).findFirst().get();
                    veBaseStudentInfoDto.setSfsqzn(value);
                } catch (Exception e) {
                    throw new RuntimeException("请填写正确的‘是否随迁子女’");
                }
            }
            if (veXueJiExcelDto.getSfjdlk() != null) {
                try {
                    String value = dictModelListMap.get("SFJDLK").stream()
                            .filter(dict -> dict.getText().equals(veXueJiExcelDto.getSfjdlk()))
                            .map(DictModel::getValue).findFirst().get();
                    veBaseStudentInfoDto.setSfjdlk(value);
                } catch (Exception e) {
                    throw new RuntimeException("请填写正确的‘是否建档立卡’");
                }
            }

            if (veXueJiExcelDto.getSfdb() != null) {
                try {
                    String value = dictModelListMap.get("SFDB").stream()
                            .filter(dict -> dict.getText().equals(veXueJiExcelDto.getSfdb()))
                            .map(DictModel::getValue).findFirst().get();
                    veBaseStudentInfoDto.setSfdb(Integer.parseInt(value));
                } catch (Exception e) {
                    throw new RuntimeException("请填写正确的‘是否低保’");
                }
            }
            if (StringUtils.isNotBlank(veXueJiExcelDto.getZsfs())) {
                try {
                    String value = dictModelListMap.get("ZSFS").stream()
                            .filter(dict -> dict.getText().equals(veXueJiExcelDto.getZsfs()))
                            .map(DictModel::getValue).findFirst().get();

                    veBaseStudentInfoDto.setZsfs(value);
                } catch (Exception e) {
                    throw new RuntimeException("请填写正确的‘招生方式’");
                }
            }
            if (veXueJiExcelDto.getSfssgjzxj() != null) {
                try {

                    String value = dictModelListMap.get("SFSSGJZXJ").stream()
                            .filter(dict -> dict.getText().equals(veXueJiExcelDto.getSfssgjzxj()))
                            .map(DictModel::getValue).findFirst().get();
                    veBaseStudentInfoDto.setSfssgjzxj(value);
                } catch (Exception e) {
                    throw new RuntimeException("请填写正确的‘是否享受国家助学金’");
                }
            }
            if (veXueJiExcelDto.getXx() != null) {
                try {
                    String value = dictModelListMap.get("XX").stream()
                            .filter(dict -> dict.getText().equals(veXueJiExcelDto.getXx()))
                            .map(DictModel::getValue).findFirst().get();
                    veBaseStudentInfoDto.setXx(value);
                } catch (Exception e) {
                    throw new RuntimeException("请填写正确的‘血型’");
                }
            }
        }

        if (StringUtils.isNotBlank(veXueJiExcelDto.getLqzy())) {
            String dict = returnDictValue("ve_base_specialty", veXueJiExcelDto.getLqzy());
            if (dict != null) {
                veBaseStudentInfoDto.setLqzyId(Integer.parseInt(dict));
                veBaseStudentInfoDto.setLqzyText(veXueJiExcelDto.getSpec());
            } else {
                throw new RuntimeException("请填写正确的‘专业名称’");

            }
        }

        if (StringUtils.isNotBlank(veXueJiExcelDto.getCsrq())) {
            try {
                Long td = Long.valueOf(DateTimeUtil.dateToTimestamp(veXueJiExcelDto.getCsrq()));
                if (td != null && td > 0) {
                    veBaseStudentInfoDto.setCsrq(Integer.parseInt(td + ""));
                } else {
                    throw new RuntimeException("请填写正确的‘出生日期’");
                }
            } catch (Exception e) {
                throw new RuntimeException("请填写正确的‘出生日期’");
            }
        }

        //籍贯所在省市区
        if (StringUtils.isNotBlank(veXueJiExcelDto.getJgszProvince())) {
            Integer dict = dictReverseForArea(veXueJiExcelDto.getJgszProvince(), 0);
            if (dict != null) {
                veBaseStudentInfoDto.setJgszProvinceId(dict);
                veBaseStudentInfoDto.setJgszProvince(veXueJiExcelDto.getJgszProvince());
            } else {
                throw new RuntimeException("请填写正确的‘籍贯所在省’");
            }
        }
        if (StringUtils.isNotBlank(veXueJiExcelDto.getJgszCity())) {
            if (veBaseStudentInfoDto.getJgszProvinceId() == null) {
                throw new RuntimeException("请填写正确的‘籍贯所在省’");
            }
            Integer dict = dictReverseForArea(veXueJiExcelDto.getJgszCity(), veBaseStudentInfoDto.getJgszProvinceId());
            if (dict != null) {
                veBaseStudentInfoDto.setJgszCityId(dict);
                veBaseStudentInfoDto.setJgszCity(veXueJiExcelDto.getJgszCity());
            } else {
                throw new RuntimeException("请填写正确的‘籍贯所在市’");
            }
        }
        if (StringUtils.isNotBlank(veXueJiExcelDto.getJgszCounty())) {
            if (veBaseStudentInfoDto.getJgszCityId() == null) {
                throw new RuntimeException("请填写正确的‘籍贯所在市’");
            }
            Integer shiId = dictReverseForArea(veXueJiExcelDto.getJgszCounty(), veBaseStudentInfoDto.getJgszCityId());
            if (shiId != null) {
                veBaseStudentInfoDto.setJgszCountyId(shiId);
                veBaseStudentInfoDto.setJgszCounty(veXueJiExcelDto.getJgszCounty());
            } else {
                throw new RuntimeException("请填写正确的‘籍贯所在区县’");
            }
        }
        //出生地所在省市区
        if (StringUtils.isNotBlank(veXueJiExcelDto.getCsdszProvince())) {
            Integer dict = dictReverseForArea(veXueJiExcelDto.getCsdszProvince(), 0);
            if (dict != null) {
                veBaseStudentInfoDto.setCsdszProvinceId(dict);
                veBaseStudentInfoDto.setCsdszProvince(veXueJiExcelDto.getCsdszProvince());
            } else {
                throw new RuntimeException("请填写正确的‘出生地所在省’");
            }
        }
        if (StringUtils.isNotBlank(veXueJiExcelDto.getCsdszCity())) {
            if (veBaseStudentInfoDto.getCsdszProvinceId() == null) {
                throw new RuntimeException("请填写正确的‘出生地所在省’");
            }
            Integer dict = dictReverseForArea(veXueJiExcelDto.getCsdszCity(), veBaseStudentInfoDto.getCsdszProvinceId());
            if (dict != null) {
                veBaseStudentInfoDto.setCsdszCityId(dict);
                veBaseStudentInfoDto.setCsdszCity(veXueJiExcelDto.getCsdszCity());
            } else {
                throw new RuntimeException("请填写正确的‘出生地所在市’");
            }
        }
        if (StringUtils.isNotBlank(veXueJiExcelDto.getCsdszCounty())) {
            if (veBaseStudentInfoDto.getCsdszCityId() == null) {
                throw new RuntimeException("请填写正确的‘出生地所在市’");
            }
            Integer shiId = dictReverseForArea(veXueJiExcelDto.getCsdszCounty(), veBaseStudentInfoDto.getCsdszCityId());
            if (shiId != null) {
                veBaseStudentInfoDto.setCsdszCountyId(shiId);
                veBaseStudentInfoDto.setCsdszCounty(veXueJiExcelDto.getCsdszCounty());
            } else {
                throw new RuntimeException("请填写正确的‘出生地所在区县’");
            }
        }


    }

    /***家庭情况字典逆转换*/
    public void dictReverseForVeStuFamilyDtoList(VeXueJiExcelDto veXueJiExcelDto, List<VeStuFamilyDto> veStuFamilyDtoList) {
        if (veXueJiExcelDto.getGxm1() != null) {
            try {
                String value = dictModelListMap.get("GXM").stream()
                        .filter(dict -> dict.getText().equals(veXueJiExcelDto.getGxm1()))
                        .map(DictModel::getValue).findFirst().get();
                veStuFamilyDtoList.get(0).setGxm(value);
            } catch (Exception e) {
                throw new RuntimeException("请填写正确的‘成员1关系’");
            }
        }
        if (veXueJiExcelDto.getSfjhr1() != null) {
            try {
                String value = dictModelListMap.get("SFJHR").stream()
                        .filter(dict -> dict.getText().equals(veXueJiExcelDto.getSfjhr1()))
                        .map(DictModel::getValue).findFirst().get();
                veStuFamilyDtoList.get(0).setSfjhr(value);
            } catch (Exception e) {
                throw new RuntimeException("请填写正确的‘成员1是否监护人’");
            }
        }
        if (veXueJiExcelDto.getSfzjlxm1() != null) {
            try {
                String value = dictModelListMap.get("SFZJLXM").stream()
                        .filter(dict -> dict.getText().equals(veXueJiExcelDto.getSfzjlxm1()))
                        .map(DictModel::getValue).findFirst().get();
                veStuFamilyDtoList.get(0).setSfzjlxm(value);
            } catch (Exception e) {
                throw new RuntimeException("请填写正确的‘成员1身份证件类型’");
            }
        }
        if (veXueJiExcelDto.getGxm2() != null) {
            try {
                String value = dictModelListMap.get("GXM").stream()
                        .filter(dict -> dict.getText().equals(veXueJiExcelDto.getGxm2()))
                        .map(DictModel::getValue).findFirst().get();
                veStuFamilyDtoList.get(1).setGxm(value);
            } catch (Exception e) {
                throw new RuntimeException("请填写正确的‘成员2关系’");
            }
        }
        if (veXueJiExcelDto.getSfjhr2() != null) {
            try {
                String value = dictModelListMap.get("SFJHR").stream()
                        .filter(dict -> dict.getText().equals(veXueJiExcelDto.getSfjhr2()))
                        .map(DictModel::getValue).findFirst().get();
                veStuFamilyDtoList.get(1).setSfjhr(value);
            } catch (Exception e) {
                throw new RuntimeException("请填写正确的‘成员2是否监护人’");
            }
        }
        if (veXueJiExcelDto.getSfzjlxm2() != null) {
            try {
                String value = dictModelListMap.get("SFZJLXM").stream()
                        .filter(dict -> dict.getText().equals(veXueJiExcelDto.getSfzjlxm2()))
                        .map(DictModel::getValue).findFirst().get();
                veStuFamilyDtoList.get(1).setSfzjlxm(value);
            } catch (Exception e) {
                throw new RuntimeException("请填写正确的‘成员2身份证件类型’");
            }
        }
        if (veXueJiExcelDto.getJtlb() != null) {
            try {
                String value = dictModelListMap.get("JTLB").stream()
                        .filter(dict -> dict.getText().equals(veXueJiExcelDto.getJtlb()))
                        .map(DictModel::getValue).findFirst().get();
                veStuFamilyDtoList.get(0).setJtlb(value);
                veStuFamilyDtoList.get(1).setJtlb(value);
            } catch (Exception e) {
                throw new RuntimeException("请填写正确的‘家庭类别’");
            }
        }
    }


    public String returnDictText(String code, String value) {
        if (dictModelListMap.get(code) == null) {
            return null;
        }
        return Optional.ofNullable(dictModelListMap.get(code))   // 空安全封装
                .orElseGet(Collections::emptyList)                  // 无匹配code时返回空列表
                .stream()
                .filter(dict -> Objects.equals(dict.getValue(), value))  // 防御性比较（允许value为null）
                .findFirst()
                .map(DictModel::getText)
                .orElse(null);
    }

    public String returnDictValue(String code, String text) {
        if (dictModelListMap.get(code) == null) {
            return null;
        }
        return Optional.ofNullable(dictModelListMap.get(code))   // 空安全封装
                .orElseGet(Collections::emptyList)                  // 无匹配code时返回空列表
                .stream()
                .filter(dict -> Objects.equals(dict.getText(), text))  // 防御性比较（允许value为null）
                .findFirst()
                .map(DictModel::getValue)
                .orElse(null);
    }

}
